home *** CD-ROM | disk | FTP | other *** search
- unit FMain;
- { See readme.txt for overview. Comments can be found with each method. }
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ShellApi,
- StdCtrls, ComCtrls, Menus, Registry,
- UPTSplitter, UPTFrame, UPTShellUtils, UPTShell95, UPTTreeList, UPTShellControls;
-
- type
- TFrmMain = class(TForm)
- PTSplitter1: TPTSplitter;
- PTShellTree1: TPTShellTree;
- PTShellList1: TPTShellList;
- MainMenu1: TMainMenu;
- File1: TMenuItem;
- Exit1: TMenuItem;
- Test1: TMenuItem;
- Memo1: TMemo;
- PTFrame1: TPTFrame;
- Registercustomicon1: TMenuItem;
- procedure PTShellTree1Change(Sender: TObject; Node: TTreeNode);
- procedure PTShellList1AddItem(aSender: TObject;
- aParentIShf: IShellFolder; aParentAbsIdList,
- aItemRelIdList: PItemIDList; aAttribs: Integer;
- var afAllowAdd: LongBool);
- procedure FormCreate(Sender: TObject);
- procedure Exit1Click(Sender: TObject);
- procedure Registercustomicon1Click(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure PTShellList1FillComplete(Sender: TObject);
- procedure PTShellList1DblClickOpen(aSender: TObject;
- var afHandled: Boolean);
- private
- public
- { Public declarations }
- end;
-
- var
- FrmMain: TFrmMain;
-
- implementation
-
- {$R *.DFM}
-
-
- type TMyObj = class FMyData: String; end; // Example class associated with non-shell nodes.
-
- const NONSHELLKEY = '__nonshell1';
-
- var gNonShellKeyRegistered: Boolean = FALSE;
-
-
- procedure TFrmMain.Exit1Click(Sender: TObject);
- begin
- Close;
- end;
-
-
- {
- The non-shell items for the shell tree are added here.
- }
- procedure TFrmMain.FormCreate(Sender: TObject);
- var n1, n2: TTreeNode;
- img: Integer;
- begin
- img := ShellGetIconIndexFromExt( '.txt', SHGFI_SMALLICON );
- {Pick an icon. We can only use system image-list icons. See below for a way of adding custom
- icons to the system image list.}
-
- n1 := PTShellTree1.Items.AddFirst( nil, 'Hello!' );
- n1.ImageIndex := img;
- n1.SelectedIndex := img;
- n1.Data := TMyObj.Create;
- TMyObj(n1.Data).FMyData := n1.Text;
-
- n2 := PTShellTree1.Items.AddChild( n1, 'World!' );
- n2.ImageIndex := img;
- n2.SelectedIndex := img;
- n2.Data := TMyObj.Create;
- TMyObj(n2.Data).FMyData := n2.Text;
-
- n1.Expand( TRUE );
- {There are a few rules when assigning non TPTShTreeData objects to the Data property of tree nodes.
-
- 1. The item must be a class. You cannot assign integers, memory allocated with GetMem or New or
- anything else. It must be a class.
- 2. It must be unique instance of a class.
- 3. The class will be automatically freed. The shell tree effectively become the owner of the object.
-
- Also note that you shouldn't assign objects to the Data property of shell nodes. Instead use the Data
- property of the TPTShTreeData object. eg.
-
- PTShellTree1.GetDataFromNode(MyTreeNode).Data := TMyObj.Create;
-
- In this case none of the non-shell node restrictions apply - you can assign non-classes.
- However, you must free the object yourself in the OnDeleteItem event handler. eg.
-
- procedure TFrmMain.PTShellTree1DeleteItem(aSender: TObject;
- aNode: TTreeNode; aShTreeData: TPTShTreeData);
- begin
- TObject(aShTreeData.Data).Free
- end;
- }
- n1.MakeVisible;
- end;
-
-
- {
- This method is called when the selection changes in the shell tree.
-
- This method checks to see if the newly selected node is a shell or non-shell node.
- If it is a non-shell node then the shell list is hidden and a panel is shown.
- }
- procedure TFrmMain.PTShellTree1Change(Sender: TObject; Node: TTreeNode);
- var f: Boolean;
- begin
- f := Node.Selected and (TObject(node.Data) is TMyObj);
- PTShellList1.Visible := not f;
- PTFrame1.Visible := f;
- if f then
- PTFrame1.Caption := 'Non-Shell Node - "' + (TObject(node.Data) as TMyObj).FMyData + '"';
- end;
-
-
- {
- This method is called for before every item is added to the shell list.
- The non-shell item is added here, above any other items.
- }
- procedure TFrmMain.PTShellList1AddItem(aSender: TObject;
- aParentIShf: IShellFolder; aParentAbsIdList, aItemRelIdList: PItemIDList;
- aAttribs: Integer; var afAllowAdd: LongBool);
- begin
- {Insert a non-shell item as the first item.}
- if PTShellList1.Items.Count = 0 then
- with PTShellList1.Items.Add do
- begin
- Caption := 'Go up';
- if gNonShellKeyRegistered then
- ImageIndex := ShellGetIconIndexFromExt( '.'+NONSHELLKEY, 0 );
- end;
- end;
-
-
- {
- If no items are added to the list, AddItem won't be called. FillComplete will be called
- in all cases though.
- }
- procedure TFrmMain.PTShellList1FillComplete(Sender: TObject);
- begin
- if PTShellList1.Items.Count = 0 then
- with PTShellList1.Items.Add do
- begin
- Caption := 'Go up';
- if gNonShellKeyRegistered then
- ImageIndex := ShellGetIconIndexFromExt( '.'+NONSHELLKEY, 0 );
- end;
- end;
-
-
- {
- This method implements the event handler for the DblClickOpen event which is
- called if the user double-clicks or presses enter on a non-folder item.
- }
- procedure TFrmMain.PTShellList1DblClickOpen(aSender: TObject;
- var afHandled: Boolean);
- begin
- if Assigned(PTShellList1.Selected) and (PTShellList1.Selected.Index = 0) then
- PTShellList1.GoUp(1);
- afHandled := TRUE;
- end;
-
-
-
- {
- The next two methods assign a custom icon (not already used by a registered file extension) to the
- non-shell item in the list view (at index 0).
-
- The procedure is to add a dummy file-type to the registry that uses the desired icon. Then
- get the index of that icon for the dummy file-type and set that non-shell item's ImageIndex
- property to that.
-
- The FormDestroy method just cleans up after us.
-
- A more robust implementation would check if the dummy key already exists. If so, try a different
- key etc.
- }
- procedure TFrmMain.Registercustomicon1Click(Sender: TObject);
- procedure RegFail;
- begin
- raise Exception.Create( 'Failed creating registry key' );
- end;
- var r: TRegistry;
- begin
- ShowMessage( 'This will temporarily register a file type with an icon and use that icon for '+
- 'the non-shell item in the list view.' );
- r := TRegistry.Create;
- try
- r.RootKey := HKEY_CLASSES_ROOT;
- if not r.OpenKey( '.'+NONSHELLKEY, TRUE ) then RegFail;
- r.WriteString( '', NONSHELLKEY );
- r.CloseKey;
-
- if not r.OpenKey( NONSHELLKEY, TRUE ) then RegFail;
- r.WriteString( '', 'Temporary key for Plasmatech Shell Control Pack Non-Shell Nodes demo' );
- if not r.OpenKey( 'DefaultIcon', TRUE ) then RegFail;
- r.WriteString( '', ExtractFilePath(Application.ExeName)+'goup.ico' );
- r.CloseKey;
-
- gNonShellKeyRegistered := TRUE;
- finally
- r.Free;
- end;
-
- PTShellList1.Items[0].ImageIndex := ShellGetIconIndexFromExt( '.'+NONSHELLKEY, 0 );
- end;
-
-
- {
- Clean up any registry mess.
- }
- procedure TFrmMain.FormDestroy(Sender: TObject);
- var r: TRegistry;
- begin
- r := TRegistry.Create;
- try
- r.RootKey := HKEY_CLASSES_ROOT;
- r.DeleteKey( NONSHELLKEY );
- r.DeleteKey( '.'+NONSHELLKEY );
- finally
- r.Free;
- end;
- end;
-
-
- end.
-
-